home *** CD-ROM | disk | FTP | other *** search
/ Developer CD Series 1998 November: Tool Chest / Dev.CD Nov 98 TC.toast / Sample Code / Snippets / Devices / SCSI Simple Sample / Src / SCSISimpleSampleDisplay.c < prev    next >
Encoding:
C/C++ Source or Header  |  1994-03-24  |  9.6 KB  |  361 lines  |  [TEXT/KAHL]

  1. /*                                SCSISimpleSampleDisplay.c                        */
  2. /*
  3.  * This module displays the results from all tests. Note that it is
  4.  * intentionally pretty crude so the entire display is described in this file;
  5.  * a "real" program would move strings to resources and, perhaps, more clearly
  6.  * explain the results.
  7.  */
  8. #include "SCSISimpleSample.h"
  9.  
  10. typedef struct {
  11.     unsigned char    senseKey;
  12.     StringPtr        senseText;
  13. } SenseKeyText;
  14.  
  15. /*
  16.  * The sense keys.
  17.  */
  18. static StringPtr        gSenseKeyText[] = {
  19.     "\pNo error",
  20.     "\pRecovered error",
  21.     "\pNot ready",
  22.     "\pMedium error",
  23.     
  24.     "\pHardware error",
  25.     "\pIllegal request",
  26.     "\pUnit attention",
  27.     "\pData protection",
  28.  
  29.     "\pBlank check",    
  30.     "\pVendor specific",
  31.     "\pCopy aborted",
  32.     "\pCommand aborted",
  33.  
  34.     "\pCompare equal",    
  35.     "\pVolume overflow",
  36.     "\pMiscompare",
  37.     "\pReserved"
  38. };
  39.  
  40. StringPtr        gScsiDeviceType[] = {
  41.     "\pDisk",
  42.     "\pTape",
  43.     "\pPrinter",
  44.     "\pProc.",
  45.     "\pWORM",
  46.     "\pCD-ROM",
  47.     "\pScanner",
  48.     "\pOptical",
  49.     "\pChanger",
  50.     "\pComm.",
  51.     "\pUnknown"
  52. };
  53.  
  54. StringPtr        gScsiState[] = {
  55.     "\pNot Ready",
  56.     "\pBecoming Ready",
  57.     "\pUnit Attention",
  58.     "\pBusy",
  59.     "\pReady",
  60.     "\pFailure"
  61. };
  62.  
  63. typedef struct CmdInfo {
  64.     unsigned short                cmdByte;
  65.     StringPtr                    text;
  66. } CmdInfo, *CmdInfoPtr;
  67. static CmdInfo                gCmdInfo[] = {
  68.     { kScsiCmdInquiry,                "\pInquiry"                        },
  69.     { kScsiCmdLogSelect,            "\pLog Select"                    },
  70.     { kScsiCmdLogSense,                "\pLog Sense"                    },
  71.     { kScsiCmdModeSelect12,            "\pMode Select [12]"            },
  72.     { kScsiCmdModeSelect6,            "\pMode Select [6]"                },
  73.     { kScsiCmdModeSense12,            "\pMode Sense [6]"                },
  74.     { kScsiCmdRequestSense,            "\pRequest Sense"                },
  75.     { kScsiCmdTestUnitReady,        "\pTest Unit Ready"                },
  76.     { kScsiCmdPreventAllowRemoval,    "\pPrevent or Allow Removal"    },
  77.     { kScsiCmdRead6,                "\pRead [6]"                    },
  78.     { kScsiCmdRead10,                "\pRead [10]"                    },
  79.     { kScsiCmdReadCapacity,            "\pRead Device Capacity"        },
  80.     { kScsiCmdReadDefectData,        "\pRead Defect Data"            },
  81.     { kScsiCmdReassignBlocks,        "\pReassign Blocks"                },
  82.     { kScsiCmdStartStopUnit,        "\pStart or Stop Unit"            },
  83.     { 0xFF,                            NULL                            }
  84. };
  85.  
  86.  
  87. /*
  88.  * ShowSCSIBusID is called before sending a command to the indicated device.
  89.  */
  90. void
  91. ShowSCSIBusID(
  92.         DeviceIdent                scsiDevice,                /* -> Bus/target/LUN    */
  93.         ConstStr255Param        commandText
  94.     )
  95. {
  96.         Str255                work;
  97.         
  98.         pstrcpy(work, "\pBus ID: ");
  99.         AppendDeviceID(work, scsiDevice);
  100.         if (commandText != NULL) {
  101.             pstrcat(work, "\p, ");
  102.             pstrcat(work, commandText);
  103.         }
  104.         LOG(work);
  105. }
  106.  
  107. /*
  108.  * Display the results of an extended sense request.
  109.  * Format the fields we understand.
  110.  */
  111. void
  112. ShowRequestSense(
  113.         register ScsiCmdBlockPtr    scsiCmdBlockPtr
  114.     )
  115. {
  116. #define SCB        (*scsiCmdBlockPtr)
  117.         DoShowRequestSense(
  118.             SCB.scsiDevice,                /* For this device                            */
  119.             SCB.status,                    /* The original error from the SCSI Manager    */
  120.             SCB.requestSenseStatus,        /* The error, if any, from Request Sense    */
  121.             &SCB.command,                /* The command that failed                    */
  122.             &SCB.sense                    /* -> the sense buffer                        */
  123.         );
  124. #undef SCB
  125. }
  126.  
  127. /*
  128.  * Actually display the results of a request sense. This is independent of the SCB
  129.  */
  130. void
  131. DoShowRequestSense(
  132.         DeviceIdent                scsiDevice,
  133.         OSErr                    operationStatus,
  134.         OSErr                    requestSenseStatus,
  135.         const SCSI_CommandPtr    scsiCommand,
  136.         const SCSI_Sense_Data    *sensePtr
  137.     )
  138. {
  139.         register int                i;
  140.         Str255                        work;
  141.         Str255                        senseMessage;
  142. #define SENSE        (*sensePtr)
  143.  
  144.         if (operationStatus != noErr) {
  145.             ShowSCSIBusID(scsiDevice, "\pOperation failed");
  146.             DoShowSCSICommand(scsiCommand, NULL);
  147.         }
  148.         if (operationStatus != noErr && operationStatus != statusErr) {
  149.             /*
  150.              * The operation failed, and the failure was severe enough that
  151.              * the device didn't return Check Condition. Perhaps there is
  152.              * no device at this bus/target.
  153.              */
  154.             ShowStatusError(scsiDevice, operationStatus, scsiCommand);
  155.         }
  156.         if (operationStatus == statusErr && requestSenseStatus == noErr) {
  157.             /*
  158.              * The operation failed, the device returned Check Condition, and
  159.              * we were able to read the Request Sense information.
  160.              */
  161.             pstrcpy(work, "\pSense: ");
  162.             if ((SENSE.errorCode & kScsiSenseInfoMask) != kScsiSenseInfoValid) {
  163.                 AppendPascalString(work, "\p(invalid sense code)");
  164.                 AppendHexLeadingZeros(work, SENSE.errorCode, 2);
  165.                 LOG(work);
  166.             }
  167.             else {
  168.                 AppendPascalString(
  169.                     work, gSenseKeyText[SENSE.senseKey & kScsiSenseKeyMask]);
  170.                 if ((SENSE.senseKey & kScsiSenseILI) != 0)
  171.                     AppendPascalString(work, "\p, Illegal Logical Length");
  172.                 if ((SENSE.senseKey & kScsiSenseEOM) != 0)
  173.                     AppendPascalString(work, "\p, End of Media");
  174.                 if ((SENSE.senseKey & kScsiSenseFileMark) != 0)
  175.                     AppendPascalString(work, "\p, File Mark");
  176.                 LOG(work);
  177.                 work[0] = 0;
  178.                 AppendPascalString(work, "\p ASC: ");
  179.                 AppendHexLeadingZeros(work, SENSE.additionalSenseCode, 2);
  180.                 AppendPascalString(work, "\p, ASQ: ");
  181.                 AppendHexLeadingZeros(work, SENSE.additionalSenseQualifier, 2);
  182.                 for (i = 1;; ++i) {
  183.                     GetIndString(
  184.                         senseMessage, SENSE.additionalSenseCode + STRS_SenseBase, i);
  185.                     if (senseMessage[0] == 0) {
  186.                         /*
  187.                          * We don't know the sense qualifier, use the default
  188.                          * additional sense code message, if any.
  189.                          */
  190.                         GetIndString(
  191.                             senseMessage,
  192.                             SENSE.additionalSenseCode + STRS_SenseBase,
  193.                             1
  194.                         );
  195.                         if (senseMessage[0] != 0)
  196.                             goto displaySense;
  197.                         break;
  198.                     }
  199.                     if (senseMessage[1] == SENSE.additionalSenseQualifier) {
  200. displaySense:            senseMessage[1] = senseMessage[0] - 1;
  201.                         AppendPascalString(work, "\p, ");
  202.                         AppendPascalString(work, (StringPtr) &senseMessage[1]);
  203.                         break;
  204.                     }
  205.                 }
  206.                 LOG(work);
  207.             }
  208.         }
  209. #undef SENSE
  210. }
  211.  
  212. /*
  213.  * This formats and displays the SCSI Manager OSErr code (with out extensions)
  214.  */
  215. void
  216. ShowStatusError(
  217.         DeviceIdent                scsiDevice,
  218.         OSErr                    errorStatus,
  219.         const SCSI_CommandPtr    scsiCommand
  220.     )
  221. {
  222.         Str255                    work;
  223.         StringHandle            errorHdl;
  224.         
  225.         if (errorStatus != noErr || gVerboseDisplay) {
  226.             pstrcpy(work, "\pDevice: ");
  227.             AppendDeviceID(work, scsiDevice);
  228.             AppendPascalString(work, "\p, ");
  229.             switch (errorStatus) {
  230.             case noErr:                AppendPascalString(work, "\pSuccessful");        break;
  231.             case scsiNonZeroStatus:    /* Continue */
  232.             case statusErr:            AppendPascalString(work, "\pCheck Condition");    break;
  233.             case controlErr:        AppendPascalString(work, "\pBusy");                break;
  234.             case scBadParmsErr:        AppendPascalString(work, "\pParam Error");        break;
  235.             case scCommErr:            AppendPascalString(work, "\pNo Device");        break;
  236.             case scPhaseErr:        AppendPascalString(work, "\pPhase Error");        break;
  237.             case scComplPhaseErr:    AppendPascalString(work, "\pBad Phase");        break;
  238.             default:
  239.                 AppendPascalString(work, "\pSystem Error ");
  240.                 AppendSigned(work, errorStatus);
  241.                 errorHdl = (StringHandle) GetResource('Estr', errorStatus);
  242.                 if (errorHdl != NULL) {
  243.                     AppendPascalString(work, "\p, \"");
  244.                     HLock((Handle) errorHdl);
  245.                     AppendPascalString(work, *errorHdl);
  246.                     HUnlock((Handle) errorHdl);
  247.                     ReleaseResource((Handle) errorHdl);
  248.                     AppendPascalString(work, "\p\"");
  249.                 }
  250.                 break;
  251.             }
  252.             LOG(work);
  253.             DoShowSCSICommand(scsiCommand, NULL);
  254.         }
  255. }
  256.  
  257. void
  258. DoShowInquiry(
  259.         DeviceIdent                scsiDevice,                /* -> Bus/target/LUN    */
  260.         const SCSI_Inquiry_Data    *inquiry
  261.     )
  262. {
  263.         unsigned short                i;
  264.         Str255                        work;
  265. #define INQUIRY        (*inquiry)
  266.  
  267.         work[0] = 0;
  268.         AppendDeviceID(work, scsiDevice);
  269.         i = INQUIRY.devType;
  270.         if (i > kScsiDevTypeMax)
  271.             i = kScsiDevTypeMax;
  272.         AppendPascalString(work, "\p: \"");
  273.         AppendPascalString(work, gScsiDeviceType[i]);
  274.         AppendPascalString(work, "\p\", \"");
  275.         AppendBytes(work, (const Ptr) INQUIRY.vendor, sizeof INQUIRY.vendor);
  276.         AppendPascalString(work, "\p\", \"");
  277.         AppendBytes(work, (const Ptr) INQUIRY.product, sizeof INQUIRY.product);
  278.         AppendPascalString(work, "\p\", \"");
  279.         AppendBytes(work, (const Ptr) INQUIRY.revision, sizeof INQUIRY.revision);
  280.         AppendPascalString(work, "\p\"");
  281.         LOG(work);
  282. #undef INQUIRY
  283. }
  284.  
  285. void
  286. DisplaySCSIErrorMessage(
  287.         OSErr                    errorStatus,
  288.         ConstStr255Param        errorText
  289.     )
  290. {
  291.         Str255                    work;
  292.         Handle                    errorMsgHdl;
  293.         
  294.         if (errorStatus != noErr) {
  295.             pstrcpy(work, "\pSCSI Error (");
  296.             AppendSigned(work, errorStatus);
  297.             AppendPascalString(work, "\p) at ");
  298.             AppendPascalString(work, (const StringPtr) errorText);
  299.             AppendChar(work, '.');
  300.             errorMsgHdl = GetResource('Estr', errorStatus);
  301.             if (errorMsgHdl != NULL) {
  302.                 AppendPascalString(work, "\p \"");
  303.                 AppendPascalString(work, (StringPtr) *errorMsgHdl);
  304.                 AppendPascalString(work, "\p\"");
  305.                 ReleaseResource(errorMsgHdl);
  306.             }
  307.             LOG(work);
  308.         }
  309. }
  310.  
  311. void
  312. DoShowSCSICommand(
  313.         const SCSI_CommandPtr    scsiCommand,
  314.         ConstStr255Param        message
  315.     )
  316. {
  317.         register CmdInfoPtr        cmdInfoPtr;
  318.         register unsigned short    i;
  319.         unsigned short            cmdBlockLength;        /* -> Length of CDB            */
  320.         Str255                    work;
  321.         
  322.         work[0] = 0;
  323.         if (message != NULL && message[0] != 0) {
  324.             AppendPascalString(work, (StringPtr) message);
  325.             AppendPascalString(work, "\p, ");
  326.         }
  327.         pstrcpy(work, "\pCommand ");
  328.         for (cmdInfoPtr = gCmdInfo; cmdInfoPtr->text != NULL; cmdInfoPtr++) {
  329.             if (cmdInfoPtr->cmdByte == scsiCommand->scsi[0]) {
  330.                 AppendPascalString(work, "\p (");
  331.                 AppendPascalString(work, cmdInfoPtr->text);
  332.                 AppendPascalString(work, "\p)");
  333.                 break;
  334.             }
  335.         }
  336.         AppendPascalString(work, "\p =");
  337.         cmdBlockLength = SCSIGetCommandLength((Ptr) scsiCommand);
  338.         if (cmdBlockLength == 0)
  339.             cmdBlockLength = sizeof (SCSI_Command);
  340.         for (i = 0; i < cmdBlockLength; i++) {
  341.             AppendChar(work, ' ');
  342.             AppendHexLeadingZeros(work, (unsigned long) scsiCommand->scsi[i], 2);
  343.         }
  344.         LOG(work);
  345. }
  346.  
  347.  
  348. void
  349. AppendDeviceID(
  350.         StringPtr                result,
  351.         DeviceIdent                scsiDevice
  352.     )
  353. {
  354.         AppendUnsigned(result, scsiDevice.bus);
  355.         AppendChar(result, '.');
  356.         AppendUnsigned(result, scsiDevice.targetID);
  357.         AppendChar(result, '.');
  358.         AppendUnsigned(result, scsiDevice.LUN);
  359. }
  360.  
  361.